package org.jdpf.core.paramserializer;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.jdpf.core.kernel.logging.ILogger;
import org.jdpf.core.kernel.logging.LoggerFactory;
import org.jdpf.core.paramserializer.services.IParamSerializer;
import org.jdpf.core.plugins.parameters.Parameters;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class ParamSerializer implements IParamSerializer {

	private static final ILogger logger=LoggerFactory.getDefault().getLogger();
	
	private Document doc;
	private String xmlParamFile;
	private Element root;
	private DocumentBuilder docBuilder;
	
	public ParamSerializer(){
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		docBuilder=null;
		try {
			docBuilder = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

	public void serializeParam(Parameters param) {
		doc=docBuilder.newDocument();
		initializeDocument();
		Element el = doc.createElement("jdpf:JDPFNet");
		String xmlNetFile = "not used";
		el.appendChild(createCommonElement("File", xmlNetFile));
		root.appendChild(el);
		
		List<String> transitionsId = param.getPluginIdList();
		for(String transId : transitionsId){
			Element parametersElement = doc.createElement("Parameters");
			parametersElement.setAttribute("transitionId", transId);
			List<String> parametersName = param.getParameterNames(transId);
			for(String paramName: parametersName){
				String value = (String)param.getParameterValue(transId, paramName);
				Element parameterElement = doc.createElement("Parameter");
				parameterElement.appendChild(createCommonElement("Name", paramName));
				parameterElement.appendChild(createCommonElement("Value", value));
				parametersElement.appendChild(parameterElement);
			}
			root.appendChild(parametersElement);
		}
		
		finalizeXMLSerialization();
	}
	
	private void initializeDocument() {
		root=doc.createElement("jdpf:JDPFParameters");
		Attr jdpf=doc.createAttribute("xmlns:jdpf");
		jdpf.setNodeValue("http://www.jdpf.org/JDPFParameters");
		root.setAttributeNode(jdpf);
		Attr xsi=doc.createAttribute("xmlns:xsi");
		xsi.setNodeValue("http://www.w3.org/2001/XMLSchema-instance");
		root.setAttributeNode(xsi);
		Attr location=doc.createAttribute("xmlns:schemaLocation");
		location.setNodeValue("http://www.jdpf.org/JDPFParameters ../org.jdpf.core.paramloader/src/main/resources/JDPFParameters.xsd");
		root.setAttributeNode(location);
	}

	private void finalizeXMLSerialization() {
		doc.appendChild(root);
		try {
			Transformer transformer=TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(xmlParamFile)));
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		logger.log("[INFO] Parameters serialize to XML format in file "+xmlParamFile);
	}
	
	
	private Element createCommonElement(String name,String text){
		Element el=doc.createElement("jdpf:"+name);
		el.setTextContent(text);
		return el;
	}

	public String getXMLParamFile() {
		return xmlParamFile;
	}

	public void setXMLParamFile(String file) {
		xmlParamFile = file;
	}

}
